package cn.itcast.bos.web.action.base;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.ServletOutputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

import cn.itcast.bos.domain.base.Area;
import cn.itcast.bos.service.base.AreaService;
import cn.itcast.bos.util.BaseAction;
import cn.itcast.bos.util.PinYin4jUtils;

/**
 * 区域类的action
 * 
 * @author 王文杰
 * @version 1.0, 2017-9-4 20:59:48
 */
@ParentPackage("json-default")
@Namespace("/")
@Controller
@Scope("prototype")
public class AreaAction extends BaseAction<Area>{
	
	/** 接收文件上传属性 */
	private File file;
	
	public void setFile(File file) {
		this.file = file;
	}
	
	/** 注入业务层对象 */
	@Autowired
	private AreaService areaService;

	/**
	 * 导入Excel文件的方法
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value="area_batchImport")
	public String batchImport() throws Exception{
		
		List<Area> areas = new ArrayList<Area>();
		// 编写解析代码的逻辑
		// 基于.xls格式解析HSSF
		// 1.加载Excel文件对象
		HSSFWorkbook hssfWorkbook = new HSSFWorkbook(new FileInputStream(file));
		// 2.读取一个sheet
		HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(0);
		// 读取sheet中每一行
		for (Row row : hssfSheet) {
			// 一行数据对应一个区域对象
			if(row.getRowNum() == 0){
				// 第一行 跳过
				continue;
			}
			// 跳过空行
			if(row.getCell(0) == null || StringUtils.isBlank(row.getCell(0).getStringCellValue())){
				continue;
			}
			// 创建一个area类封装数据
			Area area = new Area();
			area.setId(row.getCell(0).getStringCellValue());
			area.setProvince(row.getCell(1).getStringCellValue());
			area.setCity(row.getCell(2).getStringCellValue());
			area.setDistrict(row.getCell(3).getStringCellValue());
			area.setPostcode(row.getCell(4).getStringCellValue());
			// 基于pinyin4j生成城市编码和简码
			String province = area.getProvince();
			String city = area.getCity();
			String district = area.getDistrict();
			province = province.substring(0,province.length()-1);  // 去掉最后一个字   陕西省  -- 陕西
			city = city.substring(0,city.length()-1);
			district = district.substring(0, district.length()-1);
//			
//			System.out.println(province);
			// 简码
			String[] handArray = PinYin4jUtils.getHeadByString(province+city+district); // [S X W] 陕西西安未央
			StringBuffer sb = new StringBuffer();
			
			for (String str : handArray) {
				// 拼接字符串
				sb.append(str);
			}
			// 再将stringbuffer转换为字符串
			String shortcode = sb.toString();
			// 设置简码
			area.setShortcode(shortcode);
			
			// 城市编码
			String citycode = PinYin4jUtils.hanziToPinyin(city, "");
			area.setCitycode(citycode);
			
			areas.add(area);
		}
		
		// 调用业务层
		areaService.saveBatch(areas);
		return NONE;
	}

	/**
	 * 导出Excel的方法
	 * 
	 * @return 一个空的返回值
	 * @throws Exception 
	 */
	@Action(value="area_export")
	public String export() throws Exception{
		// 1.获取数据
		List<Area> list = areaService.findAll();
		
		// 2.创建一个工作薄
		HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
		// 3.创建sheet----当前sheet的内容  
		HSSFSheet sheet = hssfWorkbook.createSheet("区域信息");
		// 4.创建表头
		HSSFRow row = sheet.createRow(0);
		row.createCell(0).setCellValue("编号");
		row.createCell(1).setCellValue("省");
		row.createCell(2).setCellValue("市");
		row.createCell(3).setCellValue("区");
		row.createCell(4).setCellValue("邮编");
		row.createCell(5).setCellValue("城市编码");
		row.createCell(6).setCellValue("简码");
		// 创建ceil
		// 判断得到的list是否为空 ,也可以得到数据后先判断得到的数据
		if(list != null && list.size() > 0){
			for(int i=0;i<list.size();i++){
				// 创建行
				HSSFRow createRow = sheet.createRow(i+1);
				// 得到每一组area信息
				Area area = list.get(i);
				// 把得到的area信息填入创建的行中
				createRow.createCell(0).setCellValue(area.getId());
				createRow.createCell(1).setCellValue(area.getProvince());
				createRow.createCell(2).setCellValue(area.getCity());
				createRow.createCell(3).setCellValue(area.getDistrict());
				createRow.createCell(4).setCellValue(area.getPostcode());
				createRow.createCell(5).setCellValue(area.getCitycode());
				createRow.createCell(6).setCellValue(area.getShortcode());
			}
		}
		
		// 把工作薄写到前台进行下载
		String filename = "区域信息.xls";
		
		// 下载设置两个头一个流
		// 第一个头
		ServletActionContext.getResponse().setContentType(ServletActionContext.getServletContext().getMimeType(filename));
		
		filename = new String(filename.getBytes(),"iso8859-1");
		// 另一个头
		ServletActionContext.getResponse().setHeader("Content-Disposition", "attachment;filename="+filename);
		// 设置一个流
		ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();
		
		hssfWorkbook.write(out);
		
		return NONE;
	}

	/**
	 * 分页的方法
	 * 
	 * @return
	 */
	@Action(value="area_pageQuery",results={@Result(name="success",type="json")})
	public String pageQuery(){
		
		// 创建一个封装page 和 rows 的Pageable对象
		Pageable pageable = new PageRequest(page-1, rows);  // 一定page要减一
		
		// 根据查询条件 构造 Specification 条件查询对象 
		Specification<Area> specification = new Specification<Area>() {
			
			/**
			 *  构造条件查询方法,如果方法返回null,代表无条件查询
			 *  ROOT 参数 获取条件表达式 类似于name=?,age=? ...
			 *  CriteriaQuery参数 构造简单查询条件返回  提供where方法
			 *  CriteriaBuilder参数  构造Predicate对象,条件对象,构造复杂查询结果
			 */
			@Override
			public Predicate toPredicate(Root<Area> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// 创建一个封装 predictate 的list集合
				List<Predicate> list = new ArrayList<Predicate>();
				
				// 当查询root根对象Area
				// 单表查询 (查询当前对象对应数据)
				if(StringUtils.isNotBlank(model.getProvince())){
					// 进行 省  的区域查询
					Predicate p1 = cb.like(root.get("province").as(String.class),"%"+model.getProvince()+"%");
					list.add(p1);
				}
				if(StringUtils.isNotBlank(model.getCity())){
					// 进行 城市 的区域查询
					Predicate p2 = cb.like(root.get("city").as(String.class),"%"+model.getCity()+"%");
					list.add(p2);
				}
				if(StringUtils.isNotBlank(model.getDistrict())){
					// 进行 县/区  的区域查询
					Predicate p3 = cb.like(root.get("district").as(String.class),"%"+model.getDistrict()+"%");
					list.add(p3);
				}
				
				return cb.and(list.toArray(new Predicate[0]));
			}
		};
		
		// 在调用service 方法 查询数据
		Page<Area> pageData =  areaService.findPageData(specification,pageable);
		
		// 把数据压入值栈
		pushPageDtaToValueStack(pageData);
		
		return SUCCESS;
	}

}
